<template>
	<view class="container">
		<!-- 顶部标题 -->
		<view class="page-title">今日可约课学生</view>

		<!-- 🔍 搜索框 -->
		<view class="search-bar">
			<view class="search-input">
				<text class="icon">🔍</text>
				<input v-model="keyword" placeholder="搜索学生姓名" @input="handleSearch" class="input" />
			</view>
		</view>

		<!-- 主体列表（带滚动） -->
		<scroll-view class="list-container" scroll-y :scroll-top="scrollTop" ref="listRef" scroll-with-animation @scroll="handleScroll">
			<!-- 字母分组（A-Z全显示，即使无数据） -->
			<block v-for="group in groupedStudents" :key="group.letter">
				<!-- 分组标题（如“A”） -->
				<view class="group-title" :id="`group-${group.letter}`">
					{{ group.letter }}
				</view>

				<!-- 学生项容器（横向排列） -->
				<view class="student-list">
					<block v-for="student in group.students" :key="student.id">
						<view class="student-card" @tap="selectStudent(student)">
							<text class="card-text">*ID: {{ student.id }} {{ student.name }} ({{ student.lessons }}节课)</text>
						</view>
					</block>
				</view>
			</block>

			<!-- 空状态（无任何学生时显示） -->
			<view class="empty-state" v-if="isAllEmpty">
				<text class="empty-icon">🔍</text>
				<text class="empty-tip">暂无可约课学生</text>
			</view>
		</scroll-view>

		<!-- 右侧字母索引（固定） -->
		<view class="index-bar">
			<block v-for="letter in alphabet" :key="letter">
				<view class="index-item" :class="{ active: activeLetter === letter }" @tap="scrollToGroup(letter)">
					{{ letter }}
				</view>
			</block>
		</view>
	</view>
</template>

<script setup>
import { ref, computed, watch, nextTick, getCurrentInstance } from 'vue';

/* ------------------- 1. Props & 初始化 ------------------- */
const props = defineProps({
	// 父组件传入的原始数据（格式与图片匹配）
	rawData: {
		type: Array,
		default: () => [
			{
				type: 'a',
				list: [
					{ id: 27348, name: '阿雅', lessons: 5 },
					{ id: 34867, name: '安妮', lessons: 3 },
					{ id: 34866, name: '安莎', lessons: 1 },
					{ id: 27345, name: '阿雅', lessons: 5 },
					{ id: 34864, name: '安妮', lessons: 3 }
				]
			},
			{
				type: 'b',
				list: [
					{ id: 27341, name: '白雅', lessons: 5 },
					{ id: 34862, name: '白妮', lessons: 3 }
				]
			},
			{
				type: 'c',
				list: [
					{ id: 27341, name: '蔡雅', lessons: 5 },
					{ id: 34862, name: '蔡妮', lessons: 3 }
				]
			}
			// 其他字母数据可自行补充...
		]
	}
});
const emit = defineEmits(['select']);

/* ------------------- 2. 响应式状态 ------------------- */
const keyword = ref(''); // 搜索关键字
const activeLetter = ref('A'); // 当前高亮的索引字母
const scrollTop = ref(0); // 列表滚动位置
const listRef = ref(null); // 列表_ref
const alphabet = ref('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')); // 全字母索引

/* ------------------- 3. 计算属性（核心逻辑） ------------------- */
// 1. 处理原始数据：合并同字母分组 + 搜索过滤
const processedData = computed(() => {
	const map = {};
	// 初始化所有字母分组（即使无数据）
	alphabet.value.forEach((letter) => (map[letter] = []));
	// 合并原始数据到对应字母分组
	props.rawData.forEach((section) => {
		const letter = section.type.toUpperCase();
		if (map[letter]) {
			map[letter] = map[letter].concat(section.list);
		}
	});
	// 根据关键字过滤（不区分大小写）
	const filteredMap = {};
	Object.keys(map).forEach((letter) => {
		filteredMap[letter] = map[letter].filter((student) => student.name.toLowerCase().includes(keyword.value.trim().toLowerCase()));
	});
	return filteredMap;
});

// 2. 生成分组列表（按字母顺序排列）
const groupedStudents = computed(() => {
	return alphabet.value.map((letter) => ({
		letter: letter,
		students: processedData.value[letter]
	}));
});

// 3. 判断是否所有分组都无数据（显示空状态）
const isAllEmpty = computed(() => {
	return Object.values(processedData.value).every((list) => list.length === 0);
});

/* ------------------- 4. 方法（交互逻辑） ------------------- */
// 搜索：更新列表并滚动到第一个有数据的分组
function handleSearch() {
	nextTick(() => {
		const firstValidGroup = groupedStudents.value.find((group) => group.students.length > 0);
		if (firstValidGroup) {
			activeLetter.value = firstValidGroup.letter;
			scrollToGroup(firstValidGroup.letter);
		} else {
			activeLetter.value = 'A';
		}
	});
}

// 滚动到指定字母分组（点击索引时触发）
function scrollToGroup(letter) {
	activeLetter.value = letter;
	const instance = getCurrentInstance();
	// 查找分组标题的位置
	uni.createSelectorQuery()
		.in(instance?.proxy)
		.select(`#group-${letter}`)
		.boundingClientRect((rect) => {
			if (rect) {
				// 计算滚动偏移量（列表顶部到分组标题的距离）
				scrollTop.value = rect.top - 20; // 20rpx 偏移量（避免标题贴顶）
			}
		})
		.exec();
}

// 滚动列表时，自动更新高亮索引字母
function handleScroll() {
	const instance = getCurrentInstance();
	// 获取所有分组标题的位置
	uni.createSelectorQuery()
		.in(instance?.proxy)
		.selectAll('.group-title')
		.boundingClientRect((rects) => {
			if (!rects.length) return;
			// 找到当前可见的分组（标题顶部在列表可视区域内）
			const visibleGroup = rects.find((rect) => rect.top >= 0 && rect.top <= 100); // 100rpx 阈值（标题可见范围）
			if (visibleGroup) {
				const currentLetter = groupedStudents.value[rects.indexOf(visibleGroup)].letter;
				if (activeLetter.value !== currentLetter) {
					activeLetter.value = currentLetter;
				}
			}
		})
		.exec();
}

// 选中学生（触发父组件事件）
function selectStudent(student) {
	emit('select', student);
}

/* ------------------- 5. 生命周期 ------------------- */
// 初始化：滚动到第一个有数据的分组
watch(
	groupedStudents,
	() => {
		nextTick(() => {
			const firstValidGroup = groupedStudents.value.find((group) => group.students.length > 0);
			if (firstValidGroup) {
				activeLetter.value = firstValidGroup.letter;
				scrollToGroup(firstValidGroup.letter);
			}
		});
	},
	{ immediate: true }
);
</script>

<style scoped>
/* ------------------- 全局样式 ------------------- */
* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}

.container {
	position: relative;
	width: 100%;
	min-height: 100vh;
	background-color: #f5f7fa;
	padding-bottom: 20rpx;
}

/* ------------------- 顶部标题 ------------------- */
.page-title {
	font-size: 36rpx;
	font-weight: 700;
	color: #333;
	margin: 20rpx 30rpx;
	padding-top: 20rpx;
}

/* ------------------- 搜索框 ------------------- */
.search-bar {
	padding: 0 30rpx 20rpx;
}

.search-input {
	display: flex;
	align-items: center;
	background-color: #fff;
	border-radius: 14rpx;
	padding: 0 20rpx;
	height: 70rpx;
}

.search-input .icon {
	font-size: 28rpx;
	color: #999;
	margin-right: 12rpx;
}

.search-input .input {
	flex: 1;
	height: 100%;
	font-size: 28rpx;
	color: #333;
}

/* ------------------- 列表容器 ------------------- */
.list-container {
	height: calc(100vh - 180rpx); /* 减去标题和搜索框高度 */
	padding: 0 30rpx;
}

/* ------------------- 分组标题 ------------------- */
.group-title {
	font-size: 32rpx;
	font-weight: 700;
	color: #666;
	margin: 20rpx 0;
	padding-top: 20rpx;
	border-top: 1rpx solid #eaeaea;
}

/* ------------------- 学生列表（横向布局） ------------------- */
.student-list {
	display: flex;
	flex-wrap: wrap;
	gap: 15rpx; /* 学生项之间的间隔 */
}

/* ------------------- 学生卡片（匹配图片样式） ------------------- */
.student-card {
	flex: 0 0 calc(33.33% - 10rpx); /* 3列布局（每列占1/3宽度） */
	background-color: #fff;
	border: 1rpx solid #eaeaea;
	border-radius: 10rpx;
	padding: 15rpx;
	font-size: 26rpx;
	color: #333;
	margin-bottom: 15rpx;
	cursor: pointer;
}

/* ------------------- 空状态 ------------------- */
.empty-state {
	display: flex;
	flex-direction: column;
	align-items: center;
	margin-top: 120rpx;
}

.empty-icon {
	font-size: 80rpx;
	color: #999;
	opacity: 0.6;
}

.empty-tip {
	font-size: 30rpx;
	color: #999;
	margin-top: 20rpx;
}

/* ------------------- 右侧索引栏（固定） ------------------- */
.index-bar {
	position: fixed;
	right: 10rpx;
	top: 50%;
	transform: translateY(-50%);
	background-color: rgba(255, 255, 255, 0.9);
	border-radius: 24rpx;
	padding: 10rpx 0;
	box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
	z-index: 999;
	width: 44rpx;
	height: calc(100vh - 200rpx); /* 限制高度（显示滚动条） */
	overflow-y: auto;
}

/* ------------------- 索引项 ------------------- */
.index-item {
	width: 44rpx;
	height: 44rpx;
	line-height: 44rpx;
	text-align: center;
	font-size: 28rpx;
	color: #6a11cb;
	margin: 4rpx 0;
	cursor: pointer;
}

/* ------------------- 激活的索引项（高亮） ------------------- */
.index-item.active {
	background: linear-gradient(135deg, #6a11cb, #2575fc);
	color: #fff;
	border-radius: 50%;
}
</style>
